package com.service.Impl;

import com.dto.CommentDetailDto;
import com.dto.CommentWithRepliesDto;
import com.entity.*;
import com.exception.AddException;
import com.exception.DateNotFoundException;
import com.exception.UpdateException;
import com.mapper.OrderMapper;
import com.mapper.ProductReviewsMapper;
import com.mapper.ReviewLikesMapper;
import com.mapper.UserMapper;
import com.service.ProductReviewsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName ProductReviewsServiceImpl
 * @Description 商品评论业务层实现类
 * @Author Kx
 * @Date 2025/6/9 9:06
 * @Version 1.0
 */
@Service("productReviews")
public class ProductReviewsServiceImpl implements ProductReviewsService {
    private final ProductReviewsMapper productReviewsMapper;
    private final OrderMapper orderMapper;
    private final UserMapper userMapper;
    private final ReviewLikesMapper reviewLikesMapper;

    public ProductReviewsServiceImpl(ProductReviewsMapper productReviewsMapper, OrderMapper orderMapper, UserMapper userMapper, ReviewLikesMapper reviewLikesMapper) {
        this.productReviewsMapper = productReviewsMapper;
        this.orderMapper = orderMapper;
        this.userMapper = userMapper;
        this.reviewLikesMapper = reviewLikesMapper;
    }

    /**
     * @param productReviews : 商品评论信息
     * @author: kx
     * @date: 2025/6/9 9:07
     * @description: 添加商品评论信息
     */
    @Transactional // 开启事务
    @Override
    public void addProductReview(ProductReviews productReviews) {
        // 获取订单商品项信息
        Order order = orderMapper.findLatestOrderForUserAndProduct(productReviews.getUserId(), productReviews.getProductId());

        // 判断用户是否购买了此商品
        if (order == null) {
            throw new DateNotFoundException(1001, "只有购买商品的用户才能评论此商品");
        }

        // 设置订单编号
        productReviews.setOrderId(order.getOrderId());
        // 设置创建时间
        productReviews.setCreatedAt(LocalDateTime.now());

        try {
            productReviewsMapper.addProductReview(productReviews);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AddException(1002, "添加商品评论失败");
        }
    }

    /**
     * @author: kx
     * @date: 2025/6/10 8:42
     * @param productReviews : 商品评论信息
     * @description: 修改商品评论状态
    */
    @Transactional // 开启事务
    @Override
    public void updateStatus(ProductReviews productReviews) {
        try {
            productReviewsMapper.updateStatus(productReviews);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UpdateException(1003,"修改商品评论状态失败");
        }
    }

    /**
     * @author: kx
     * @date: 2025/6/10 11:45
     * @param replies : 商品回复信息
     * @return java.util.List<com.dto.CommentWithRepliesDto>
     * @description: 构建回复树形结构
    */
    private List<CommentWithRepliesDto> buildCommentWithRepliesDtoList(List<ReviewReplies> replies) {
        List<CommentWithRepliesDto> commentWithRepliesDtoList = new ArrayList<>();

        for (ReviewReplies productReviews : replies) {
            // 创建数据传输对象
            CommentWithRepliesDto commentWithRepliesDto = new CommentWithRepliesDto();
            // 设置回复信息
            commentWithRepliesDto.setReviewReplies(productReviews);

            // 设置回复人
            commentWithRepliesDto.setUser(userMapper.findByUserId(productReviews.getUserId()));
            // 设置评论点赞量
            commentWithRepliesDto.setCommentLikeCount(reviewLikesMapper.findByReplyId(productReviews.getReplyId()));

            // 判断是否是回复别人的回复
            if (productReviews.getParentReplyId() == null) {
                // 获取主评论信息
                ProductReviews productReviews1 = productReviewsMapper.findByReviewId(productReviews.getReviewId());
                // 设置被回复人
                commentWithRepliesDto.setReplyUser(userMapper.findByUserId(productReviews1.getUserId()));
            } else {
                // 获取回复信息
                ReviewReplies reviewReplies = productReviewsMapper.findReplyById(productReviews.getParentReplyId());
                // 设置被回复人
                commentWithRepliesDto.setReplyUser(userMapper.findByUserId(reviewReplies.getUserId()));
            }
            // 递归获取子回复
            List<ReviewReplies> reviewReplies = productReviewsMapper.findRepliesByParentId(productReviews.getReplyId());
            // 创建子回复DTO列表
            List<CommentWithRepliesDto> childDtoS = buildCommentWithRepliesDtoList(reviewReplies);
            // 设置子回复
            commentWithRepliesDto.setReplies(childDtoS);

            // 添加到结果集
            commentWithRepliesDtoList.add(commentWithRepliesDto);
        }
        return commentWithRepliesDtoList;
    }

    /**
     * @param productId : 商品ID
     * @return java.util.List<com.entity.ProductReviews>
     * @author: kx
     * @date: 2025/6/10 8:53
     * @description: 根据商品编号查询该商品的所有评论及回复信息
     */
    @Override
    public List<CommentDetailDto> findByProductId(Integer productId) {

        List<CommentDetailDto> commentDetailDtoList = new ArrayList<>();

        // 获取该商品下的所有评论
        List<ProductReviews> productReviews = productReviewsMapper.findByProductId(productId);

        for (ProductReviews productReviews1 : productReviews) {
            CommentDetailDto commentDetailDto = new CommentDetailDto();
            // 设置商品评论信息
            commentDetailDto.setProductReviews(productReviews1);
            // 设置用户信息
            commentDetailDto.setUser(userMapper.findByUserId(productReviews1.getUserId()));
            // 设置评论点赞量
            commentDetailDto.setCommentLikeCount(reviewLikesMapper.findByReviewId(productReviews1.getReviewId()));

            // 获取该评论下的所有回复
            List<ReviewReplies> reviewReplies = productReviewsMapper.findRepliesByReviewId(productReviews1.getReviewId());

            // 构建树形结构
            List<CommentWithRepliesDto> commentWithRepliesDtos = buildCommentWithRepliesDtoList(reviewReplies);

            // 设置到评论详情中
            commentDetailDto.setReplies(commentWithRepliesDtos);

            // 添加到结果集中
            commentDetailDtoList.add(commentDetailDto);
        }
        return commentDetailDtoList;
    }

    /**
     * @author: kx
     * @date: 2025/6/10 20:42
     * @param reviewReplies : 评论回复信息
     * @description: 添加评论回复信息
    */
    @Transactional
    @Override
    public void addReviewReplies(ReviewReplies reviewReplies) {
        // 设置创建时间
        reviewReplies.setCreatedAt(LocalDateTime.now());
        try {
            productReviewsMapper.addReviewReplies(reviewReplies);
        } catch (Exception e) {
            throw new AddException(1002, "添加评论回复失败");
        }
    }

    /**
     * @author: kx
     * @date: 2025/6/10 20:54
     * @param reviewReplies : 评论回复信息
     * @description: 修改评论回复信息状态
    */
    @Transactional
    @Override
    public void updateReviewReplies(ReviewReplies reviewReplies) {
        try {
            productReviewsMapper.updateReviewReplies(reviewReplies);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UpdateException(1003,"修改评论回复失败");
        }
    }
}
